package com.nx.arch.addon.lock.lock;

import java.util.Calendar;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;

import org.springframework.util.StringUtils;

import com.nx.arch.addon.lock.NxLock;
import com.nx.arch.addon.lock.NxLockClient;
import com.nx.arch.addon.lock.client.EtcdClient;
import com.nx.arch.addon.lock.exception.LockException;
//import com.nx.arch.addon.lock.monitor.ReportClientVersionTask;

/**
 * @类名称 EtcdSolution.java
 * @类描述 etcd 锁方案
 * @作者  庄梦蝶殇 linhuaichuan@naixuejiaoyu.com
 * @创建时间 2020年3月28日 下午4:08:32
 * @版本 1.0.0
 *
 * @修改记录
 * <pre>
 *     版本                       修改人 		修改日期 		 修改内容描述
 *     ----------------------------------------------
 *     1.0.0 		庄梦蝶殇 	2020年3月28日             
 *     ----------------------------------------------
 * </pre>
 */
public class EtcdSolution implements NxLockClient {
    
    private EtcdClient etcdclient;
    
    /**
     * etcd节点列表
     */
    private String[] baseUrl;
    
    /**
     * 集群名
     */
    private String clusterName;
    
    private int timeout;
    
    private static final ScheduledExecutorService scheduledExecutor = Executors.newSingleThreadScheduledExecutor(new ThreadFactory() {
        @Override
        public Thread newThread(Runnable runnable) {
            Thread thread = Executors.defaultThreadFactory().newThread(runnable);
            thread.setDaemon(true);
            return thread;
        }
    });
    
    public EtcdSolution connectionString(String... baseUrl) {
        this.baseUrl = baseUrl;
        return this;
    }
    
    public EtcdSolution clusterName(String clusterName) {
        this.clusterName = clusterName;
        return this;
    }
    
    /**
     * 单位ms，设置后调用acquire方法最大等待时间
     *
     * @param timeout
     * @return
     */
    public EtcdSolution timeout(int timeout) {
        if (timeout < 5 || timeout > TimeUnit.SECONDS.toMillis(2)) {
            throw new IllegalArgumentException("timeout 取值区间【2," + TimeUnit.SECONDS.toMillis(2) + "】");
        }
        this.timeout = timeout;
        return this;
    }
    
    @Override
    public NxLockClient build()
        throws LockException {
        if (baseUrl != null && baseUrl.length > 0) {
            timeout = timeout == 0 ? 1000 : timeout;
            this.etcdclient = EtcdClient.getInstance(baseUrl);
        }
        if (StringUtils.isEmpty(clusterName)) {
            throw new LockException("clusterName is must param , please add clusterName param");
        }
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.MILLISECOND, 0);
        // long initialDelay = calendar.getTimeInMillis() - System.currentTimeMillis();
        // scheduledExecutor.scheduleAtFixedRate(new ReportClientVersionTask(clusterName), initialDelay, 24, TimeUnit.HOURS);
        return this;
    }
    
    @Override
    public NxLock newLock(String lockKey)
        throws LockException {
        return newLock(lockKey, false);
    }
    
    @Override
    public NxLock newLock(String lockKey, boolean reentrant)
        throws LockException {
        return new EtcdLock(etcdclient, clusterName, lockKey, reentrant);
    }
    
    @Override
    public synchronized void close()
        throws LockException {
        try {
            if (scheduledExecutor != null) {
                // scheduledExecutor.shutdown();
            }
        } catch (RuntimeException e) {
            throw new LockException("close lockclient exception", e);
        }
    }
}
